﻿using CommonTools;
using Newtonsoft.Json;
using shop.Model;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace shop.Bll.cost
{
    public class tradeItemBll
    {
        /// <summary> 可能重复的 </summary>
        //public async Task<List<Result>> CheckError(DateTime begin, DateTime end)
        //{


        //}

        public async Task<PageQueryResult<dynamic>> Query(DateTime? begin, DateTime? end, tradeItem find , int pageNo, int pageSize)
        {
            begin= begin.ToDate();
            end= end.LastTimeOfDay();

            var shopers = await DB.FSql.Select<ShopPerson>()
                .Where(a => a.isdel == false)
                .ToListAsync();

            var list = await DB.FSql.Select<tradeItem, OutStockItem, LogiInfo,GoodsOperator>()
                .InnerJoin((a, b, c,d) => a.trade_no == b.trade_no && a.spec_no == b.spec_no && a.num == b.num )
                .LeftJoin((a,b,c, d) => a.logistics_name== c.logistics_name && c.isdel== false && c.logistics_name!="无")
                .LeftJoin((a,b,c,d) => a.platform_goods_id== d.platform_goods_id && d.isdel== false)
                //.LeftJoin((a,b,c,d, e) => (a.shop_name== e.Shop || (a.platform_spec_id==e.PersonId && string.IsNullOrEmpty( a.platform_spec_id)== false ) ) && e.isdel== false)
                .WhereIf(begin != null, (a, b, c, d) => b.consign_time >= begin)
                .WhereIf(end != null, (a, b, c, d) => b.consign_time <= end)
                .WhereIf(!string.IsNullOrEmpty(find?.shop_name), (a, b, c, d) => a.shop_name == find.shop_name)
                .WhereIf(!string.IsNullOrEmpty(find?.logistics_no), (a, b, c, d ) => a.logistics_no == find.logistics_no)
                .WhereIf(!string.IsNullOrEmpty(find?.logistics_name), (a, b, c, d ) => a.logistics_name == find.logistics_name)
                .WhereIf(!string.IsNullOrEmpty(find?.warehouse), (a, b, c, d) => a.warehouse == find.warehouse)
                .WhereIf(!string.IsNullOrEmpty(find?.goods_name), (a, b, c, d ) => a.goods_name == find.goods_name)
                .WhereIf(!string.IsNullOrEmpty(find?.trade_no), (a, b, c, d) => a.trade_no == find.trade_no)
                .WhereIf(!string.IsNullOrEmpty(find?.spec_no), (a, b, c, d ) => a.spec_no== find.spec_no)
                .WhereIf(!string.IsNullOrEmpty(find?.src_tids), (a, b, c, d ) => a.src_tids == find.src_tids)
                .WhereIf(!string.IsNullOrEmpty(find?.Operator), (a, b, c,d ) => d.Operator == find.Operator)
                .WhereIf(!string.IsNullOrEmpty(find?.platform_goods_id), (a, b, c,d ) => a.platform_goods_id== find.platform_goods_id)
                .Page(pageNo, pageSize)
                .Count(out var c)
                .ToListAsync((a, b, c, d) => new
                {
                    a.id,
                    订单编号 = a.trade_no,
                    店铺名称 = a.shop_name,
                    仓库 = a.warehouse,
                    原始单号 = a.src_tids,
                    订单状态 = a.trade_status,
                    订单类型 = a.trade_type,
                    退款状态 = a.refund_status,
                    交易时间 = a.trade_time,
                    付款时间 = a.pay_time,
                    发货时间= b.consign_time,
                    订单支付金额 = a.paid,
                    收件人地区 = a.receiver_district,
                    物流公司名称 = a.logistics_name,
                    快递老板= c.LogiAcct,
                    物流单号 = a.logistics_no,
                    客服备注 = a.cs_remark,
                    备注 = a.remark,
                    客服标旗 = a.cs_flag,
                    商家编码 = a.spec_no,
                    货品编号 = a.goods_no,
                    货品名称 = a.goods_name,
                    规格名称 = a.spec_name,
                    平台货品名称 = a.api_goods_name,
                    平台规格名称 = a.api_spec_name,
                    下单数量 = a.num,
                    实发数量 = a.actual_num,
                    平台货品ID = a.platform_goods_id,
                    平台规格ID = a.platform_spec_id,
                    分销商=a.fenxiao_nick,
                    来源组合装编码= b.suite_no,
                    来源组合装数量 = b.from_assembly_qty,
                    b.consign_time,
                    outStockId = b.Id,
                    d.Operator,
                    //shopPerson= e.Name,
                });
            

            //去除重复
            var res = list
                .GroupBy(a=> new { a.id, a.订单编号, a.店铺名称, a.仓库, a.原始单号, a.订单状态, a.订单类型, a.退款状态, a.交易时间, a.付款时间,a.发货时间, a.订单支付金额, a.收件人地区, a.物流公司名称,a.快递老板 , a.物流单号, a.客服备注, a.备注, a.客服标旗, a.商家编码, a.货品编号, a.货品名称, a.规格名称, a.平台货品名称, a.平台规格名称, a.下单数量, a.实发数量, a.平台货品ID, a.平台规格ID,a.分销商,a.来源组合装编码,a.来源组合装数量, a.Operator })
                .Select(a=> new
                {
                    a.Key.id,
                    a.Key.订单编号,
                    a.Key.店铺名称,
                    a.Key.仓库,
                    a.Key.分销商,
                    a.Key.原始单号,
                    a.Key.订单状态,
                    a.Key.订单类型,
                    a.Key.退款状态,
                    a.Key.交易时间,
                    a.Key.付款时间,
                    a.Key.发货时间,
                    a.Key.订单支付金额,
                    a.Key.收件人地区,
                    收件人省份 = GetProv(a.Key.收件人地区),
                    a.Key.物流公司名称,
                    a.Key.快递老板,
                    a.Key.物流单号,
                    a.Key.客服备注,
                    a.Key.备注,
                    a.Key.客服标旗,
                    a.Key.商家编码,
                    a.Key.货品编号,
                    a.Key.货品名称,
                    a.Key.规格名称,
                    a.Key.平台货品名称,
                    a.Key.平台规格名称,
                    a.Key.下单数量,
                    a.Key.实发数量,
                    a.Key.平台货品ID,
                    a.Key.平台规格ID,
                    a.Key.来源组合装编码,
                    a.Key.来源组合装数量,
                    运营负责人 = a.Key.Operator,
                    店铺负责人= shopers
                        .Where(e=> (a.Key.店铺名称 == e.Shop || (a.Key.平台规格ID == e.PersonId && string.IsNullOrEmpty(a.Key.平台规格ID) == false)))
                        .FirstOrDefault()?.Name ?? string.Empty,
                })
                .ToList();


            return new PageQueryResult<dynamic>(true, null, res, c);
        }


        private string GetProv(string receiver_district)
        {
            if (string.IsNullOrEmpty(receiver_district))
            {
                return string.Empty;
            }
            var arr = receiver_district.Split(' ');
            if (arr.Length >0)
            {
                return arr[0].Replace("省","").Replace("市","");
            }
            else
            {
                return string.Empty;
            }
        }

        private string GetCity(string receiver_district)
        {
            if (string.IsNullOrEmpty(receiver_district))
            {
                return string.Empty;
            }
            var arr = receiver_district.Split(' ');
            if (arr.Length > 1)
            {
                return arr[1];
            }
            else
            {
                return string.Empty;
            }
        }


        bool isAgentItem(string logi, IEnumerable<PostPriceDto> postPrice, IEnumerable<PostQtyPrice> postQtyPrice)
        {
            if (logi.Contains("代发"))
                return true;

            if (postPrice.Any(a => a.logistics_name == logi) || postQtyPrice.Any(a => a.logistics_name == logi))
                return false;

            return true;
        }


        /// <summary> 查询成本 </summary>
        public async Task<IEnumerable<CostModel>> QueryCost(tradeItemQueryDto find )
        {
            var workTime = DateTime.Now;
            DateTime? sqlBegin = null;
            DateTime? sqlEnd = null;


            var begin = find.begin.Date;
            var end = find.end.LastTimeOfDay();

            if (find.UseTime == true)
            {
                sqlBegin = find.begin;
                sqlEnd = find.end;
            }
            else
            {
                sqlBegin = begin;
                sqlEnd = end;
            }
       


            var list1 = await DB.FSql.Select<tradeItem, OutStockItem, LogiInfo, GoodsOperator>()
                .InnerJoin((a, b, c, d) => a.trade_no == b.trade_no && a.spec_no == b.spec_no && a.num == b.num)
                .LeftJoin((a, b, c, d ) => a.logistics_name == c.logistics_name && c.isdel == false && c.logistics_name != "无")
                .LeftJoin((a, b, c, d ) => a.platform_goods_id == d.platform_goods_id && d.isdel == false)
                //.LeftJoin((a,b,c,d) => (a.shop_name== e.Shop || (a.platform_spec_id==e.PersonId && string.IsNullOrEmpty( a.platform_spec_id)== false ) ) && e.isdel== false)
                //await DB.FSql.Select<tradeItem, OutStockItem, LogiInfo, GoodsOperator>()
                //.InnerJoin((a, b, c, d) => a.trade_no == b.trade_no && a.spec_no == b.spec_no && a.num == b.num)
                //.LeftJoin((a, b, c, d) => a.logistics_name == c.logistics_name && c.isdel == false)
                //.LeftJoin((a,b,c,d) => a.platform_goods_id== d.platform_goods_id && d.isdel== false)
                .WhereIf(begin != null, (a, b, c, d) => b.consign_time >= sqlBegin)
                .WhereIf(end != null, (a, b, c, d) => b.consign_time <= sqlEnd)
                .WhereIf(!string.IsNullOrEmpty(find?.shop_name), (a, b, c, d) => a.shop_name == find.shop_name)
                .WhereIf(!string.IsNullOrEmpty(find?.logistics_no), (a, b, c, d) => a.logistics_no == find.logistics_no)
                .WhereIf(!string.IsNullOrEmpty(find?.logistics_name), (a, b, c, d) => a.logistics_name == find.logistics_name)
                .WhereIf(!string.IsNullOrEmpty(find?.warehouse), (a, b, c, d) => a.warehouse == find.warehouse)
                .WhereIf(!string.IsNullOrEmpty(find?.goods_name), (a, b, c, d) => a.goods_name == find.goods_name)
                .WhereIf(!string.IsNullOrEmpty(find?.trade_no), (a, b, c, d) => a.trade_no == find.trade_no)
                .WhereIf(!string.IsNullOrEmpty(find?.spec_no), (a, b, c, d) => a.spec_no == find.spec_no)
                .WhereIf(!string.IsNullOrEmpty(find?.src_tids), (a, b, c, d) => a.src_tids == find.src_tids)
                .WhereIf(!string.IsNullOrEmpty(find?.Opertaor), (a, b, c, d) => d.Operator == find.Opertaor)
                .WhereIf(!string.IsNullOrEmpty(find?.platform_goods_id), (a, b, c,d) => a.platform_goods_id== find.platform_goods_id)
                .ToListAsync((a, b, c, d) => new
                {
                    a.id,
                    a.trade_no,
                    a.shop_name,
                    a.warehouse,
                    a.src_tids,
                    a.trade_status,
                    a.trade_type,
                    a.refund_status,
                    a.trade_time,
                    a.pay_time,
                    b.consign_time,
                    a.paid,
                    a.receiver_district,
                    a.logistics_name,
                    c.LogiAcct,
                    a.logistics_no,
                    a.cs_remark,
                    a.remark,
                    a.cs_flag,
                    a.spec_no,
                    a.goods_no,
                    a.goods_name,
                    a.spec_name,
                    a.api_goods_name,
                    a.api_spec_name,
                    a.num,
                    a.actual_num,
                    a.platform_goods_id,
                    a.platform_spec_id,
                    a.fenxiao_nick,
                    b.suite_no,
                    a.suit_no,
                    b.from_assembly_qty,
                    outStockId = b.Id,
                    d.Operator,
                    //shopPerson= e.Name,
                    //b.pay_time,
                });

            var shopers = await DB.FSql.Select<ShopPerson>()
            .Where(a => a.isdel == false)
            .ToListAsync();


            // 退款
            var refund = await DB.FSql.Select<RefundDoc, OutStockItem, RefundDocItem>()
                .InnerJoin((a, b,c ) => a.Tid == b.src_tid)
                .InnerJoin((a,b,c) => a.Id== c.DocId && (b.spec_name== c.specName || c.platform == "拼多多")  && b.src_oid == c.src_oid )
                .Where((a, b, c) => a.isdel == false)
                .WhereIf(begin != null, (a, b, c) => b.consign_time >= sqlBegin)
                .WhereIf(end != null, (a, b, c) => b.consign_time <= sqlEnd)
                .WhereIf(!string.IsNullOrEmpty(find?.shop_name), (a, b, c) => b.shop_name == find.shop_name)
                .WhereIf(!string.IsNullOrEmpty(find?.logistics_no), (a, b,c) => b.logistics_no == find.logistics_no)
                .WhereIf(!string.IsNullOrEmpty(find?.logistics_name), (a, b, c) => b.logistics_name == find.logistics_name)
                .WhereIf(!string.IsNullOrEmpty(find?.warehouse), (a, b, c) => b.warehouse == find.warehouse)
                .WhereIf(!string.IsNullOrEmpty(find?.goods_name), (a, b, c) => b.goods_name == find.goods_name)
                .WhereIf(!string.IsNullOrEmpty(find?.trade_no), (a, b, c) => b.trade_no == find.trade_no)
                .WhereIf(!string.IsNullOrEmpty(find?.spec_no), (a, b, c) => b.spec_no == find.spec_no)
                .WhereIf(!string.IsNullOrEmpty(find?.src_tids), (a, b, c) => b.src_tids == find.src_tids)
                //.WhereIf(!string.IsNullOrEmpty(find?.Opertaor), (a, b) => b.Operator == find.Opertaor)
                .WhereIf(!string.IsNullOrEmpty(find?.platform_goods_id), (a, b, c) => b.platform_goods_id == find.platform_goods_id)
                .ToListAsync((a,b,c) => new {a.Id, a.RefundNo, a.RefundAmount, a.ActualRefundAmount,a.RefundType, a.Tid, c.total_amount, c.specName });

    //        var refund = await DB.FSql.Select<RefundDoc, OutStockItem, RefundDocItem>()
    //.InnerJoin((a, b, c) => a.Tid == b.src_tid)
    //.Where((a, b) => a.isdel == false)
    //.WhereIf(begin != null, (a, b) => b.consign_time >= sqlBegin)
    //.WhereIf(end != null, (a, b) => b.consign_time <= sqlEnd)
    //.WhereIf(!string.IsNullOrEmpty(find?.shop_name), (a, b) => b.shop_name == find.shop_name)
    //.WhereIf(!string.IsNullOrEmpty(find?.logistics_no), (a, b) => b.logistics_no == find.logistics_no)
    //.WhereIf(!string.IsNullOrEmpty(find?.logistics_name), (a, b) => b.logistics_name == find.logistics_name)
    //.WhereIf(!string.IsNullOrEmpty(find?.warehouse), (a, b) => b.warehouse == find.warehouse)
    //.WhereIf(!string.IsNullOrEmpty(find?.goods_name), (a, b) => b.goods_name == find.goods_name)
    //.WhereIf(!string.IsNullOrEmpty(find?.trade_no), (a, b) => b.trade_no == find.trade_no)
    //.WhereIf(!string.IsNullOrEmpty(find?.spec_no), (a, b) => b.spec_no == find.spec_no)
    //.WhereIf(!string.IsNullOrEmpty(find?.src_tids), (a, b) => b.src_tids == find.src_tids)
    ////.WhereIf(!string.IsNullOrEmpty(find?.Opertaor), (a, b) => b.Operator == find.Opertaor)
    //.WhereIf(!string.IsNullOrEmpty(find?.platform_goods_id), (a, b) => b.platform_goods_id == find.platform_goods_id)
    //.ToListAsync(a => a.t1);



            var minDate = list1.Min(a => a.consign_time).ToDate() ?? begin;
            var maxDate = list1.Max(a => a.consign_time).LastTimeOfDay() ?? end;

            // 运费价格
            var postPrice = (await DB.FSql.Select<PostPrice>()
                .Where(a => a.isdel == false && a.EndDate >= minDate && a.BeginDate <= maxDate)
                .ToListAsync())
                .Select(a => PostPriceBll.ToDto(a))
                .ToList();


            var postQtyPrice = (await DB.FSql.Select<PostQtyPrice>()
                .Where(a => a.isdel == false)
                .Where(a => a.EndDate >= begin || a.EndDate == null)
                .Where(a => a.BeginDate <= end)
                .ToListAsync())
                .Select(a =>
                {
                    //a.provShort = ((string.IsNullOrEmpty(a.province) == false && a.province.Length >= 2) ? a.province.Substring(0, 2) : a.province) ?? string.Empty;
                    a.logistics_name = a.logistics_name.Replace(" ", string.Empty);
                    return a;
                })
                .ToList();

            var loInfos = (await DB.FSql.Select<LogiInfo>()
                .Where(a => a.isdel == false && a.LogiAcct.Contains("作废") == false && a.LogiAcct.Contains("代发") == false)
                .ToListAsync(a => new { a.logistics_name, a.LogiAcct }))
                .Select(a => new { logistics_name = a.logistics_name.Replace(" ", string.Empty), a.LogiAcct });


            //去除重复,  suite_no 是出库的, 
            var repeat = list1.GroupBy(a=> a.id)
                .Select(a=>new {
                    a.Key,
                    count = a.Count(),
                    outstock = a.Select(c=> new { c.outStockId, c.suite_no,c.suit_no, c.from_assembly_qty }).ToList(), 
                })
                .Where(a=> a.count>1)
                .Select(a=>
                {
                    var test = a.outstock.Where(a => a.suit_no == a.suite_no).FirstOrDefault();
                    if (test != null)
                    {
                        // 使用一个 sute_no 一样的
                        return new {a.Key, test.outStockId};
                    }
                    else
                    {
                        // 找不到区别, 随便用一个
                        return new {a.Key, outStockId= a.outstock.FirstOrDefault()?.outStockId ?? 0 };
                    }
                })
                .ToList();



            var list = list1
                    //重复问题的
                .Where(a => repeat.Any(c=> c.Key == a.id && c.outStockId == a.outStockId) == false)
                .GroupBy(a => new { a.id, a.trade_no, a.shop_name, a.warehouse, a.src_tids,a.pay_time, a.trade_status, a.trade_type, a.refund_status, a.trade_time, a.consign_time, a.paid, a.receiver_district, a.logistics_name, a.LogiAcct, a.logistics_no, a.cs_remark, a.remark, a.cs_flag, a.spec_no, a.goods_no, a.goods_name, a.spec_name, a.api_goods_name, a.api_spec_name, a.num, a.actual_num, a.platform_goods_id, a.platform_spec_id, a.fenxiao_nick, a.suit_no, a.from_assembly_qty, a.Operator })
                .Select(a =>
                {

                    var lname = a.Key.logistics_name.Replace(" ", string.Empty);
                    var linfo = a.Key.LogiAcct;
                    if(string.IsNullOrEmpty( a.Key.LogiAcct))
                    {
                        linfo = loInfos.FirstOrDefault(c => c.logistics_name == lname)?.LogiAcct;
                    }

                    return new CostModel()
                    {
                        consign_time = (a.Key.consign_time ?? DateTime.MinValue).Date,
                        trade_no = a.Key.trade_no,
                        shop_name = a.Key.shop_name,
                        warehouse = a.Key.warehouse,
                        fenxiao = a.Key.fenxiao_nick,
                        src_tids = a.Key.src_tids,
                        receiver_district = a.Key.receiver_district,
                        receiver_prov = GetProv(a.Key.receiver_district),
                        city = GetCity(a.Key.receiver_district),
                        paid = a.Key.paid ?? 0m,
                        logistics_name = lname,
                        logiAcct = linfo,
                        logistics_no = a.Key.logistics_no,
                        cs_remark = a.Key.cs_remark,
                        remark = a.Key.remark,
                        cs_flag = a.Key.cs_flag,
                        spec_no = a.Key.spec_no,
                        goods_no = a.Key.goods_no,
                        goods_name = a.Key.goods_name,
                        spec_name = a.Key.spec_name,
                        api_goods_name = a.Key.api_goods_name,
                        api_spec_name = a.Key.api_spec_name,
                        num = a.Key.num,
                        actual_num = a.Key.actual_num,
                        calc_num = a.Key.actual_num,
                        platform_goods_id = a.Key.platform_goods_id,
                        platform_spec_id = a.Key.platform_spec_id,
                        isAgent = isAgentItem(lname, postPrice, postQtyPrice),  //按物流公司分 
                        suite_no = a.Key.suit_no,
                        from_assembly_qty = a.Key.from_assembly_qty,
                        trade_type = a.Key.trade_type,
                        Operator = a.Key.Operator,
                        //ShopPerson = a.Key.shopPerson,
                        ShopPerson = shopers
                            .Where(e => (a.Key.shop_name == e.Shop || (a.Key.platform_spec_id == e.PersonId && string.IsNullOrEmpty(a.Key.platform_spec_id) == false)))
                            .FirstOrDefault()?.Name ?? string.Empty,
                        payTime = a.Key.pay_time,
                    };
                })
                .ToList();

            //物流资费计算策略
            var calcs = await DB.FSql.Select<LogiCalc, PostCalcStrategy>()
                .InnerJoin((a, b) => a.CalcMethod == b.Name)
                .Where((a, b) => string.IsNullOrEmpty(a.Logi) == false && b.isdel == false && b.isDetails == false)
                .ToListAsync((a, b) => new PostCalcStrategyDto()
                {
                    Logi = a.Logi,
                    Name = a.CalcMethod,
                    AddWeight = b.AddWeight,
                    MaxWeight = b.MaxWeight
                });


            // 货品价格表
            var goodsCosts = (await DB.FSql.Select<GoodsPrice>()
                .Where(a => a.isdel == false)
                .Where(a => a.EndDate >= minDate)
                .Where(a => a.BeginDate <= maxDate)
                .ToListAsync())
                .Select(a =>
                {
                    if (a.QtyTimes <= 0) a.QtyTimes = 1;
                    a.spec_no= a.spec_no?.Replace(" ", string.Empty);  //删除空格

                    return a;
                })
                .ToList();

            //
            var specPrices = await DB.FSql.Select<SpecialPost>()
                .Where(a => a.isdel == false).ToListAsync();

            //代发加收
            var dai = await DB.FSql.Select<DaifaAdd>()
                .Where(a => a.isdel == false)
                .Where(a=> a.BeginDate<= end)
                .Where(a=> a.EndDate>= begin)
                .ToListAsync();


            var mult = await GetMultPost(); //多把


            // 并行任务

            Parallel.ForEach(list, item =>
            {
            // 有时候相同物流单号会有多行, 需要汇总多行计算他的代发运费
            //相同物流单号发货的总数量
            //var numTemp = item.calc_post_num = list
            //    .Where(a => a.logistics_no == item.logistics_no && a.goods_no == item.goods_no)
            //    .Sum(a => a.actual_num);

            if ((item.goods_no == "五梁椅" || item.goods_no == "wuliaogyi" || item.goods_no == "wuliangyi") && item.spec_no.Contains("坐垫") == false)
            {
                //计算成本使用的数量, 
                item.calc_cost_num2 = item.actual_num * GetTimesInSpecNo(item.spec_no, 1, null);   // 需要使用原数量乘以倍数, 但是五粮椅没有指定倍数
                item.calc_post_num = item.calc_cost_num = list.Where(a => a.logistics_no == item.logistics_no && a.spec_no.Contains("坐垫") == false)
                    .Sum(a => a.actual_num * GetTimesInSpecNo(a.spec_no, 1, null));
            }
            else
            {
                //计算成本使用的数量, 
                item.calc_cost_num2 = item.actual_num;
                item.calc_post_num = item.calc_cost_num = list.Where(a => a.logistics_no == item.logistics_no && a.goods_no == item.goods_no)
                    .Sum(a => a.actual_num);
            }


            var g = FindCostPrice(goodsCosts, item.spec_no, item.goods_no, item.warehouse, item.calc_cost_num, item.consign_time, item);
            if (g != null && g.QtyTimes > 1)
            {
                //数量倍数计算后的数量
                item.calc_num = g.QtyTimes * item.calc_post_num;
            }


            //多把
            var mu = mult
                .Where(a => a.goods_no?.Equals(item.goods_no, StringComparison.CurrentCultureIgnoreCase) == true)
                .Where(a => item.consign_time >= a.BeginDate && item.consign_time <= a.EndDate)
                .Where(a => a.Keyword?.Any(b => item.cs_remark.Contains(b) && string.IsNullOrEmpty(item.cs_remark) == false) == true)
                .ToList(); //多把

            if (mu.Any() == false)
            {
                //按照数量再找一下
                mu = mult
                .Where(a => a.goods_no?.Equals(item.goods_no, StringComparison.CurrentCultureIgnoreCase) == true)
                .Where(a => item.consign_time >= a.BeginDate && item.consign_time <= a.EndDate)
                .Where(a => a.Qty > 1 && a.Qty == item.calc_post_num)    //actual_num priceNum
                .ToList(); //多把
            }

            //if( mu == null && item.Volume <=0 && item.fWeight<=0)
            //{
            //    mu = mult
            //    .Where(a => a.goods_no?.Equals(item.goods_no, StringComparison.CurrentCultureIgnoreCase) == true)
            //    .Where(a => a.Qty == item.calc_post_num)    //actual_num priceNum
            //    .FirstOrDefault(); //多把
            //}
            MultPostPrice findMu;

            if (mu.Any() && mu.Where(a => string.IsNullOrWhiteSpace(a.SpecNoFilter) == false).Any())
            {
                //需要按照商家编码再次筛选
                var ff = mu.Where(a => string.IsNullOrWhiteSpace(a.SpecNoFilter) == false && item.spec_no.Contains(a.SpecNoFilter))
                    .FirstOrDefault();
                if (ff != null)
                {
                    findMu = ff;
                }
                else
                {
                    findMu = mu.FirstOrDefault(a => string.IsNullOrWhiteSpace(a.SpecNoFilter));
                }
            }
            else
            {
                findMu = mu.FirstOrDefault();
            }

            if (findMu != null && findMu.Volume <= 0)
            {
                findMu.Volume = findMu.Flength * findMu.Width * findMu.Height;
            }

            item.Mu = findMu;


            item.goodsPrice = g?.Price ?? 0m;  //成本


            //如果是代发的, 直接使用成本标准中的邮费
            if (item.isAgent)
            {

                if (g != null)
                {

                    if (!string.IsNullOrEmpty(g.PostLogi1) && item.logistics_name.Contains(g.PostLogi1))
                    {
                        item.calc_post_cost = g.PostPrice1 * item.calc_num;  //代发运费1
                    }
                    else if (!string.IsNullOrEmpty(g.PostLogi2) && item.logistics_name.Contains(g.PostLogi2))
                    {
                        item.calc_post_cost = g.PostPrice2 * item.calc_num;  //代发运费2
                    }
                    else
                    {
                        item.calc_post_cost = g.PostPrice * item.calc_num;  //代发运费
                    }
                }

                    //代发加收

                    var dfTemp = dai.Where(a => a.Stock == item.warehouse && item.consign_time >= a.BeginDate && item.consign_time <= a.EndDate);

                //var df = dfTemp.Where(a => a.Province?.Contains(item.provShort) == true && string.IsNullOrEmpty(a.spen_no) == false && item.spec_no == a.spen_no && string.IsNullOrEmpty( a.LogiName) == false && item.logistics_name.Contains(a.LogiName) );
                var df = dfTemp.Where(a => a.Province?.Contains(item.provShort) == true && string.IsNullOrEmpty(a.spen_no) == false && item.spec_no == a.spen_no);
                if (!df.Any()) df = dfTemp.Where(a => a.Province?.Contains(item.provShort) == true && string.IsNullOrEmpty(a.spen_no) == false && item.spec_no.StartsWith(a.spen_no));
                if (!df.Any()) df = dfTemp.Where(a => a.Province?.Contains(item.provShort) == true && string.IsNullOrEmpty(a.spen_no));
                if (!df.Any()) df = dfTemp.Where(a => string.IsNullOrEmpty(a.Province) && string.IsNullOrEmpty(a.spen_no) == true && a.ByPostAmount > 0 && a.ByPostAmount == item.calc_post_cost);  //按邮费加收
                if (!df.Any()) df = dfTemp.Where(a => string.IsNullOrEmpty(a.Province) && string.IsNullOrEmpty(a.spen_no) == false && item.spec_no.StartsWith(a.spen_no));  //不要省份
                if (!df.Any()) df = dfTemp.Where(a => string.IsNullOrEmpty(a.Province) && string.IsNullOrEmpty(a.spen_no));  //不要省份, 不要编码

                    //var cc = dai.Where(a => a.LogiName == "崔庄子四折床京广线下").ToList();
                    //var cc1 = dai.Where(a => a.LogiName == "崔庄子四折床京广线下" && a.Stock == item.warehouse).ToList();

                    if (df.Any())
                    {
                        //是否需要检查快递公司
                        if (df.Any(a => string.IsNullOrEmpty(a.LogiName) == false ))
                        {
                            // 需要筛选
                            var tempDf = df.Where(a => string.IsNullOrEmpty(a.LogiName) == false && item.logistics_name.Contains(a.LogiName));
                            
                            if (tempDf.Any())
                            {
                                df = tempDf;
                            }
                            else
                            {
                                df = df.Where(a => string.IsNullOrEmpty(a.LogiName));
                            }
                        }


                        //是否需要检查城市
                        if (df.Any(a=> a.Province?.Contains(" ")==true || a.Province?.Contains("　")== true))
                        {
                            // 有城市的, 再
                            var tcity = item.city.Substring(0, 2);
                            var citys = df.Where(a => (a.Province.Contains(" ") || a.Province.Contains("　")) && a.Province.Contains(tcity))
                                .FirstOrDefault();

                            if (citys != null)
                            {
                                item.DaifaAdd = citys.AddAmount * item.actual_num;
                            }
                            else
                            {
                                //没有标记城市, 使用无城市的
                                var finddf = df.Where(a => a.Province?.Contains(" ") == false && a.Province?.Contains("　") == false).FirstOrDefault();
                                item.DaifaAdd = (finddf?.AddAmount ?? 0m) * item.actual_num;
                            }
                        }
                        else
                        {
                            //没有标记城市, 使用无城市的
                            var finddf = df.Where(a => string.IsNullOrEmpty(a.Province) || (a.Province?.Contains(" ") == false && a.Province?.Contains("　") == false) ).FirstOrDefault();
                            item.DaifaAdd = (finddf?.AddAmount ?? 0m) * item.actual_num;
                        }

                    }
                }

                //体积
                if (g != null)
                {
                    item.Volume = (g.Flength * g.Width * g.Height) * item.actual_num;
                    item.fWeight = g.FWeight * item.actual_num;
                }
            });


            #region 来源组合装: 会修改数据的体积重量, 

            var suiteList = list.Where(a => string.IsNullOrEmpty(a.suite_no) == false && a.isAgent == false)
                .GroupBy(a => new { a.src_tids, a.suite_no, a.logistics_no, a.from_assembly_qty });


            Parallel.ForEach(suiteList.ToList(), (item, loopState) =>
            {
                //原始单号一个快递单号的  货物数量  超过1的, 不用计算来源组合装
                var num = item.Sum(c => c.calc_num);
                if (num > 1)
                {
                    // 使用组合装的编号查找抛重比, 重新计算邮费
                    //list  是不是已经合并数量了 
                    var suiteNo = item.Key.suite_no;
                    var warehouse = item.FirstOrDefault().warehouse;
                    var time = item.FirstOrDefault().consign_time;

                    var g = FindCostPrice(goodsCosts, suiteNo, "xxxxxxx_xxx", warehouse, num, time.Date, null);// 只是查询计算运费的体积, 不适用单价

                    foreach (var model in item)
                    {
                        model.remark += ",来源组合装";

                        //体积
                        if (g != null)
                        {
                            model.Volume = (g.Flength * g.Width * g.Height) * model.calc_num / num;
                            model.fWeight = g.FWeight * model.calc_num / num;
                        }

                        //多把
                        var mu = mult
                            .Where(a=> model.consign_time>= a.BeginDate && model.consign_time<=  a.EndDate)
                            .Where(a => a.goods_no?.Equals(model.goods_no, StringComparison.CurrentCultureIgnoreCase) == true)
                            .Where(a => a.Keyword?.Any(b => model.cs_remark.Contains(b) && string.IsNullOrEmpty(model.cs_remark) == false) == true)
                            .ToList(); //多把
                        if (mu == null)
                        {
                            //按照数量再找一下
                            mu = mult
                            .Where(a => a.goods_no?.Equals(model.goods_no, StringComparison.CurrentCultureIgnoreCase) == true)
                            .Where(a=> model.consign_time>= a.BeginDate && model.consign_time<=  a.EndDate)
                            .Where(a => a.Qty > 1 && a.Qty == num)    //actual_num priceNum
                            .ToList(); //多把
                        }


                        MultPostPrice findMu;

                        if (mu.Any() && mu.Where(a => string.IsNullOrWhiteSpace(a.SpecNoFilter) == false).Any())
                        {
                            //需要按照商家编码再次筛选
                            var ff1 = mu.Where(a => string.IsNullOrWhiteSpace(a.SpecNoFilter) == false && model.spec_no.Contains(a.SpecNoFilter))
                                .FirstOrDefault();
                            if (ff1 != null)
                            {
                                findMu = ff1;
                            }
                            else
                            {
                                findMu = mu.FirstOrDefault(a => string.IsNullOrWhiteSpace(a.SpecNoFilter));
                            }
                        }
                        else
                        {
                            findMu = mu.FirstOrDefault();
                        }


                        if (findMu != null && findMu.Volume <= 0)
                        {
                            findMu.Volume = findMu.Flength * findMu.Width * findMu.Height;
                        }
                        model.Mu = findMu;
                    }

                    //组合装, 多行数据按一行计算运费
                    var ff = item.FirstOrDefault();
                    var t1 = new CostModel()
                    {
                        spec_no = ff.suite_no,
                        num = ff.num,
                        actual_num = ff.actual_num,
                        calc_cost_num = ff.calc_cost_num2,
                        calc_cost_num2 = ff.calc_cost_num2,
                        calc_num = ff.calc_num,
                        calc_post_num = ff.calc_cost_num2,
                        provShort = ff.provShort,
                        shop_name = ff.shop_name,
                        logiAcct = ff.logiAcct,
                        logistics_name = ff.logistics_name,
                        city = ff.city,
                        receiver_prov = ff.receiver_prov,
                        warehouse = ff.warehouse,
                        Mu = ff.Mu,
                        goods_no = ff.goods_no,
                        Volume = item.Sum(c => c.Volume),
                        fWeight = item.Sum(c => c.fWeight),
                        consign_time= item.Max(c=> c.consign_time),
                        payTime= ff.payTime,
                    };

                    CalcutePostAmount(postPrice, t1, calcs, t1.Mu, specPrices, postQtyPrice);
                    var cnt = item.Count();
                    foreach (var item2 in item)
                    {
                        item2.calc_post_cost = Math.Round(t1.calc_post_cost / cnt, 6);
                    }

                }

            });


            #endregion



            // 代发运费按数量计算的 
            var daifaQtyPost = (await DB.FSql.Select<DaifaQtyPost>()
                .Where(a => a.isdel == false)
                .Where(a => a.EndDate >= begin)
                .Where(a => a.BeginDate <= end)
                .ToListAsync())
                .Select(a => new
                {
                    a.Stock,
                    a.Province,
                    a.BeginDate,
                    a.EndDate,
                    priceList = string.IsNullOrEmpty(a.RangePriceJson)
                        ? new List<QtyPriceRange>()
                        : JsonConvert.DeserializeObject<List<QtyPriceRange>>(a.RangePriceJson),

                    specList = string.IsNullOrEmpty(a.spec_no)
                        ? new string[0]
                        : a.spec_no.Split(',', ' '),
                })
                .SelectMany(a => a.priceList.Select(c => new
                {
                    a.Stock,
                    a.Province,
                    a.BeginDate,
                    a.EndDate,
                    a.specList,
                    c.Qty,
                    c.Price,
                }))
                .ToList();


            // 店铺返点 = 单品支付金额 * 比例
            var fand = await DB.FSql.Select<ShopReward>()
                .Where(a => a.isdel == false && a.reward != 0)
                .ToListAsync(a => new { a.shop, a.reward });

            // 5. 刷单费用
            var sd = await DB.FSql.Select<Shuadan, LogiInfo>()
                .LeftJoin((a, b) => a.shopGroup == b.LogiCompany && b.isdel == false)
                .Where((a, b) => a.isdel == false)
                .ToListAsync((a, b) => new { a.shopGroup, b.logistics_name, a.MinAmount, a.MaxAmount, a.Fee, });

            var defaultSd = sd.Where(a => string.IsNullOrEmpty(a.shopGroup)).ToList();  //没有指定店铺的默认刷单价格
            var sdStocks = (await DB.FSql.Select<ShuadanConfig>().ToListAsync())
                .Select(a => a.ShuadanStock)
                .ToArray();


            // 6. 自己快递发货的     补发件   一单设置8元运费
            var bf = await DB.FSql.Select<ShuadanConfig>()
                .Where(a => string.IsNullOrEmpty(a.Bufa) == false)
                .ToOneAsync();

            Parallel.ForEach(list, item => 
            {
                bool notComputePost = false;
                if (item.isAgent)
                {
                    //检查是不是代发指定运费
                    var findDf = daifaQtyPost
                        .Where(a => a.Stock == item.warehouse && a.Province?.Contains(item.provShort) == true
                        && a.specList.Contains (item.spec_no))
                        .Where(a => item.calc_num <= a.Qty && item.consign_time >= a.BeginDate && item.consign_time<= a.EndDate)
                        .OrderByDescending(a => a.Qty)
                        .FirstOrDefault();

                    if (findDf != null)
                    {
                        item.calc_post_cost = item.calc_num * findDf.Price;
                        //continue;
                        notComputePost = true;  //不再计算运费了
                    }
                }


                //按数量计费,
                //按重量计费 = 面单+ 体积/抛重比*单价

                //计算运费: 需要在检查是否多把之后再计算运费
                if (notComputePost == false && (item.remark.Contains("组合装")== false || item.isAgent ))
                    CalcutePostAmount(postPrice, item, calcs, item.Mu, specPrices, postQtyPrice);


                //返点 拼多多是0.01    天猫店 0.055
                var fan = fand.FirstOrDefault(a => a.shop == item.shop_name);
                if (fan != null)
                    item.fandian = fan.reward * item.paid;


                if (sdStocks.Contains(item.warehouse))
                {
                    var sua = sd.Where(a => a.logistics_name == item.logistics_name)
                        .Where(a => item.paid >= a.MinAmount && item.paid <= a.MaxAmount)
                        .FirstOrDefault();

                    if (sua == null)
                    {
                        //使用默认的价格
                        sua = defaultSd.Where(a => item.paid >= a.MinAmount && item.paid <= a.MaxAmount)
                            .FirstOrDefault();
                    }

                    item.shuadan = sua.Fee;
                    item.paid = 0;  //刷单的支付金额改成0 
                }

                //
                if (bf != null && item.isAgent == false && item.trade_type == bf.Bufa)
                {
                    item.remark += ",补发";
                    item.calc_post_cost = bf.BufaPost;
                }


                // 计算退款候后的 成本, 金额
                var refd = refund.Where(a => a.Tid == item.src_tids).ToList();
                if (refd.Count > 0)
                {
                    var refundAmount = refd.Sum(c => c.ActualRefundAmount);
                    var tkbth = refd.Any(c => c.RefundType == "退款不退货");
                    item.RefundAmount = refundAmount;
                    item.RefundNo = string.Join(",", refd.Select(a => a.RefundNo).ToArray());

                    if (tkbth)
                    {
                        // 改付款, 不改成本
                        item.PayAmountRefund = -item.paid;
                    }
                    else
                    {
                        if (refundAmount >= item.amountByNum)
                        {
                            item.PayAmountRefund = -item.paid;
                            item.CostAmountRefund = -item.CostAmount;
                        }
                        else
                        {
                            item.PayAmountRefund = -refundAmount;
                            //按照比例扣成本
                            item.CostAmountRefund = Math.Round(refundAmount/ item.paid*item.CostAmount, 2, MidpointRounding.AwayFromZero)  ;
                        }
                    }
                }



            });

            // 利润 = 支付金额 - (货品单价*发货数量) - 预估邮费 - 代发加收 - 刷单费用 - 返利
            // 利润率 = 利润 / (货品单价*发货数量)
            var res = list.Select(a=>
            {
                // 计提退款+补件+退款成功的利润（销售额的0.0336）    
                a.OtherCost = a.shop_name == "分销店铺-平台类型看客服备注" ? 0 : a.paid * 0.0336m;
                a.Profit = Math.Round( a.paid-a.OtherCost - a.goodsPrice * a.calc_cost_num2 - a.calc_post_cost - a.DaifaAdd - a.shuadan- a.fandian,3);
                a.ProfitRatio = (a.goodsPrice != 0 && a.calc_cost_num2 != 0) ? (a.Profit) / (a.goodsPrice * a.calc_cost_num2) : 0m;
                a.remark = a.remark + (a.actual_num == 0 ? ",实发是0" : string.Empty);
                a.CostAmount = a.goodsPrice * a.calc_cost_num2;

                return a;

            })
                //.Select(a => new
            //{
            //    发货时间 = a.consign_time,
            //    订单编号 = a.trade_no,
            //    店铺名称 = a.shop_name,
            //    仓库 = a.warehouse,
            //    分销商 = a.fenxiao,
            //    原始单号 = a.src_tids,
            //    订单类型 = a.trade_type,
            //    收件人地区 = a.receiver_district,
            //    收件人省份 = a.receiver_prov,
            //    物流公司名称 = a.logistics_name,
            //    快递老板 = a.logiAcct,
            //    物流单号 = a.logistics_no,
            //    客服备注 = a.cs_remark,
            //    客服标旗 = a.cs_flag,
            //    商家编码 = a.spec_no,
            //    货品编号 = a.goods_no,
            //    货品名称 = a.goods_name,
            //    规格名称 = a.spec_name,
            //    平台货品名称 = a.api_goods_name,
            //    平台规格名称 = a.api_spec_name,

            //    平台货品ID = a.platform_goods_id,
            //    平台规格ID = a.platform_spec_id,
            //    来源组合装编码 = a.suite_no,
            //    是否代发 = a.isAgent ? "是" : "否",
            //    是否多把 = a.IsMult ? "是" : "否",
            //    下单数量 = a.num,
            //    实发数量 = a.actual_num,
            //    订单支付金额 = a.paid,
            //    成本 = a.goodsPrice,
            //    成本金额 = a.goodsPrice * a.calc_cost_num2,
            //    运费 = a.calc_post_cost,
            //    代发加收 = a.DaifaAdd,
            //    返点 = a.fandian,
            //    刷单手续费 = a.shuadan,
            //    利润 = a.paid - a.goodsPrice * a.calc_cost_num2 - a.calc_post_cost - a.DaifaAdd - a.shuadan,
            //    利润占比 = (a.goodsPrice != 0 && a.calc_cost_num2 != 0) ? (a.paid - a.goodsPrice * a.calc_cost_num2 - a.calc_post_cost - a.DaifaAdd - a.shuadan) / (a.goodsPrice * a.calc_cost_num2) : 0m,
            //    备注 = a.remark + (a.actual_num == 0 ? ",实发是0" : string.Empty),
            //    计算数量 = a.calc_num,
            //    运营负责人 = a.Operator,
            //})
                .ToList();


            var span = DateTime.Now - workTime;
            var str = span.ToString();
            NLog.LogManager.GetLogger("queryCost").Info("任务时长:"+ str+", "+span.TotalSeconds.ToString());
            return res;
        }


        /// <summary> 查询成本单价与 </summary>
        public GoodsPrice FindCostPrice(IEnumerable<GoodsPrice> goodsCosts, string spec_no,string goods_no, string warehouse, 
            decimal num, DateTime conTime, CostModel model)
        {
            conTime = conTime.Date;
            spec_no = spec_no.Replace(" ", "");

            GoodsPrice[] gprice = null;


            // 先找一下组合装编码
            if (!string.IsNullOrEmpty( model?.suite_no))
            {
                gprice  = goodsCosts
                    .Where(a => a.Stock == warehouse)
                    .Where(a => (a.suite_no == model.suite_no && string.IsNullOrEmpty(a.suite_no) == false))
                    .Where(a => conTime >= a.BeginDate && conTime <= a.EndDate) // todo 成本还需要继续维护截止日期
                    .Where(a => a.MinQty <= 0 || (a.MinQty > 0 && num >= a.MinQty))
                    .Where(a => a.MaxQty <= 0 || (a.MaxQty > 0 && num <= a.MaxQty))
                    .OrderBy(a => string.IsNullOrEmpty(a.spec_no) ? 99 : 0) //优先使用商家编码匹配
                    .Take(2)
                    .ToArray();
            }


            if(gprice == null || gprice.Length==0 )
            {
                gprice = goodsCosts
                    .Where(a => a.Stock == warehouse)
                    //.Where(a => a.spec_no == spec_no && string.IsNullOrEmpty(a.spec_no) == false)
                    .Where(a => (a.spec_no == spec_no && string.IsNullOrEmpty(a.spec_no) == false) || (a.goods_no == goods_no && string.IsNullOrEmpty(a.goods_no) == false))
                    .Where(a => conTime >= a.BeginDate && conTime <= a.EndDate) // todo 成本还需要继续维护截止日期
                    .Where(a => a.MinQty <= 0 || (a.MinQty > 0 && num >= a.MinQty))
                    .Where(a => a.MaxQty <= 0 || (a.MaxQty > 0 && num <= a.MaxQty))
                    .OrderBy(a => string.IsNullOrEmpty(a.spec_no) ? 99 : 0) //优先使用商家编码匹配
                    .Take(2)
                    .ToArray();
            }


            if (gprice.Length == 0)
            {
                //找不到就忽略数量, 
                var g = goodsCosts
                    .Where(a => a.Stock == warehouse)
                    //.Where(a => a.spec_no == spec_no && string.IsNullOrEmpty(a.spec_no) == false)
                    .Where(a => (a.spec_no == spec_no && string.IsNullOrEmpty(a.spec_no) == false) || (a.goods_no == goods_no && string.IsNullOrEmpty(a.goods_no) == false))
                    .Where(a => conTime >= a.BeginDate && conTime <= a.EndDate)
                    .OrderByDescending(a => a.MaxQty)
                    .FirstOrDefault();

                if (g != null)
                {
                    //gprice = new[] { g };
                    return g;
                }
                else
                {
                    if(model != null ) model.remark += ("" + "没有找到单价");

                    return null;
                }
            }
            else
            {
                if(gprice.Length>1)
                {
                    if (model != null) model.remark += ", 单价匹配到两个";
                }
                return gprice[0];
            }
        }

        /// <summary> 面单 </summary>
        const decimal _miandan = 4;

        //private decimal CalcutePriceByWeight(PostPriceDto post, IEnumerable<PostCalcStrategyDto> calcs, decimal volume, decimal ratio, 
        //    decimal? mulWeight , CostModel model)

        //amountByWei = CalcutePriceByWeight(a,calcs, mu?.Volume ?? item.Volume,  (mu == null ?  a.weightRatio : 10000), mu?.FWeight, item),

        private decimal CalcutePriceByWeight(PostPriceDto post, IEnumerable<PostCalcStrategyDto> calcs,
            MultPostPrice mul, CostModel model)
        {
            if (post == null )
            {
                return 0;
            }

            decimal ratio = post.weightRatio >0 ? post.weightRatio : 10000;
            decimal wei;

            if (mul != null)
            {
                // 取  实重与 拋比的  最大值   当计费重量
                decimal paobi = 0m;

                if (ratio>0 && mul.Volume > 0)   // && mul.weightRatio<=0  mul.weightRatio 是计算的重量, 不是抛比
                {
                    paobi = mul.Volume / ratio;
                }

                wei = Math.Max(paobi, mul.FWeight);
            }
            else
            {
                wei = model.Volume / ratio;
                wei = Math.Max(wei, model.fWeight);   //多把重量与抛重取较大值
            }


            if (post.roundMode == "向上取整" || string.IsNullOrEmpty(post.roundMode))
                wei = Math.Ceiling(wei);
            else
                wei = Math.Round(wei, 0);

            //计算策略
            if (wei> 0)
            {
                var calc = calcs.Where(a => a.Logi == model.logistics_name)
                    .Where(a => a.MaxWeight >= wei)
                    .OrderBy(a => a.MaxWeight)
                    .FirstOrDefault();
                if(calc != null)
                {
                    wei += calc.AddWeight;
                }

            }


            //按重量计费 = 面单 + 体积 / 抛重比 * 单价  需要区分区间

            decimal amount = _miandan;

            //先找特殊区间
            var spec = post.SpceialRangeList
                .Where(a => wei <= a.WeightRange)
                .OrderBy(a => a.WeightRange)
                .FirstOrDefault();

            if (spec != null) 
            {
                amount = spec.Price;
            }
            else
            {
                //没有在特殊区间,
                var common = post.CommonRangeList.Where(a => wei <= a.WeightRange)
                    .OrderBy(a => a.WeightRange)
                    .FirstOrDefault();

                //没有指定区间的价格 , 使用第一个
                if (common == null)
                {
                    common = post.CommonRangeList.Where(a => a.WeightRange == 0).FirstOrDefault();
                }

                if (common != null)
                {
                    amount = Math.Max(post.MinAmount, common.Price * wei + _miandan);
                }

            }
            
            if (model.goods_no== "wuliangyi" || model.goods_no == "五梁椅" || model.goods_no == "wuliaogyi")
            {
                // 五梁椅 多把, 
                amount = Math.Round(amount , 4);
            }
            else if ( model.calc_post_num > model.calc_num)
            {
                amount =Math.Round( amount / model.calc_post_num * model.calc_num,4);
            }
            return amount;
        }



        /// <summary> 计算运费 </summary>
        private void CalcutePostAmount(IEnumerable<PostPriceDto> postPrice, CostModel item,
           List<PostCalcStrategyDto> calcs , MultPostPrice mu, List<SpecialPost> specPrices,
            List<PostQtyPrice> postQtyPrice)
        {

            var weiFee = postPrice
                .Where(a => a.provinceJson.Contains(item.receiver_prov) && a.logistics_name == item.logistics_name)
                .Where(a => string.IsNullOrEmpty(a.StockJson) || a.StockJson.Contains(item.warehouse))
                .Where(a=> item.consign_time >= a.BeginDate )
                .OrderByDescending(a => a.BeginDate)
                .FirstOrDefault();


            if (weiFee != null)
            {
                var wf = new
                {
                    //amountByWei = CalcutePriceByWeight(a,calcs, mu?.Volume ?? item.Volume,  (mu == null ?  a.weightRatio : 10000), mu?.FWeight, item),
                    amountByWei = CalcutePriceByWeight(weiFee, calcs, mu, item),
                    weiFee.logistics_name,
                    weiFee.provinceJson,
                };


                item.calc_post_cost = wf.amountByWei;
                item.amountByWei = wf.amountByWei;
                item.IsMult = mu != null;
            }


            var qtyFeeFind = postQtyPrice
                .Where(a => a.province.Contains(item.provShort) == true && a.logistics_name == item.logistics_name)
                //有的需要区分商家编码
                .Where(a => string.IsNullOrEmpty(a.goods_no) == false && (a.goods_no == item.goods_no || a.goods_no == item.spec_no))
                .Where(a => item.consign_time >= a.BeginDate)
                .OrderByDescending(a => a.BeginDate)
                .FirstOrDefault();

            if(qtyFeeFind == null)
            {
                qtyFeeFind = postQtyPrice
                    .Where(a => item.consign_time >= a.BeginDate )
                    .Where(a => a.province.Contains(item.provShort) == true && a.logistics_name == item.logistics_name)
                    //不区分商家编码
                    .Where(a => string.IsNullOrEmpty(a.goods_no) == true )
                    .OrderByDescending(a => a.BeginDate)
                    .FirstOrDefault();

            }

            if (qtyFeeFind == null)
            {
                qtyFeeFind = postQtyPrice
                    .Where(a => item.consign_time >= a.BeginDate )
                    .Where(a => string.IsNullOrEmpty(a.province) && a.logistics_name == item.logistics_name)
                    //区分商家变暗
                    .Where(a=> string.IsNullOrEmpty(a.goods_no) == false && (a.goods_no == item.goods_no || a.goods_no == item.spec_no))
                    .OrderByDescending(a => a.BeginDate)
                    .FirstOrDefault();

  
                if (qtyFeeFind == null)
                {
                    qtyFeeFind = postQtyPrice
                    .Where(a => item.consign_time >= a.BeginDate)
                    .Where(a => string.IsNullOrEmpty(a.province) && a.logistics_name == item.logistics_name)
                    //不区分商家编码
                    .Where(a => string.IsNullOrEmpty(a.goods_no) == true)
                    .OrderByDescending(a => a.BeginDate)
                    .FirstOrDefault();
                }

            }

            if (qtyFeeFind != null)
            {
                item.calc_post_cost = item.amountByNum = CalcutePriceByNum(qtyFeeFind, item.calc_num);
                item.IsMult = mu != null;
            }


            if (weiFee == null && qtyFeeFind == null)
            {
                item.remark += ",没有找到快递资费";
            }

            //如果是特殊情况运费, 直接使用
            var specPrice = specPrices.Where(a => a.spec_no == item.spec_no && item.consign_time >= a.BeginDate 
                && a.Stock == item.warehouse && a.logistics_name.Contains(item.logistics_name))
                .OrderByDescending(a=> a.BeginDate)
                .FirstOrDefault();
            if (specPrice != null)
            {
                item.calc_post_cost = item.actual_num * specPrice.PostPrice;
            }
        }




        /// <summary> 按数量 </summary>
        private decimal CalcutePriceByNum(PostQtyPrice postQty, decimal qty)
        {
            if (postQty == null || postQty.PriceByQty<=0  || qty <=0 )
            {
                return 0;
            }

            return postQty.PriceByQty * qty; 
        }


        private async Task<List<MultPostPrice>> GetMultPost()
        {
            var mult = (await DB.FSql.Select<MultPostPrice>()
                .Where(a => a.isdel == false)
                .ToListAsync())
                .Select(a =>
                {

                    if (string.IsNullOrEmpty(a.CsRemarks) == false)
                    {
                        a.Keyword = new List<string>();
                        var val = a.CsRemarks.Split(',', '，');
                        foreach (var item in val)
                        {
                            if (item.Contains("把") && item.Length>=3)
                            {
                                var newVal = item.Replace("把", string.Empty);
                                if (val.Contains(newVal)== false)
                                    a.Keyword.Add(newVal);
                            }
                        }
                        a.Keyword.AddRange(val);
                    }
                    return a;
                })
                .ToList();

            return mult;
        }




        /// <summary> 查找可能错误 </summary>
        public async Task<IEnumerable< dynamic>> FindError()
        {
            // 没有日期的成本单价
            var noDatePrice = await DB.FSql.Select<GoodsPrice>()
                .Where(a => a.isdel == false && (a.BeginDate == null || a.EndDate == null))
                .ToListAsync(a => new
                {
                    a.Stock,
                    a.spec_no,
                });


            // 重复日期的成本单价
            var time = new DateTime(2066, 1, 1);

            var repeatPrice = await DB.FSql.Select<GoodsPrice, GoodsPrice>()
                .InnerJoin((a, b) => a.Stock == b.Stock && a.spec_no == b.spec_no && a.id != b.id
                    && a.MaxQty == b.MaxQty && a.MinQty == b.MinQty)
                .Where((a, b) => a.isdel == false && b.isdel == false && a.EndDate > time && b.EndDate > time && a.BeginDate > b.BeginDate)
                .ToListAsync((a, b) => new
                {
                    a.Stock,
                    a.spec_no,
                });


            // 重复的出库明细, 重复的订单

            var repeatOut = await DB.FSql.Select<OutStockItem>()
                .Where(a => string.IsNullOrEmpty(a.logistics_no) == false)
                .GroupBy(a => new { a.logistics_no, a.spec_no, a.trade_no })
                .Having(a => a.Count() > 1 && a.Max(a.Value.Id) - a.Min(a.Value.Id) > 100)
                .ToListAsync(a => new
                {
                    a.Key.trade_no,
                    a.Key.logistics_no,
                    a.Key.spec_no,
                });

            var repeatTrade = await DB.FSql.Select<tradeItem>()
                .Where(a => string.IsNullOrEmpty(a.logistics_no) == false)
                .GroupBy(a => new { a.logistics_no, a.spec_no, a.trade_no })
                .Having(a => a.Count() > 1 && a.Max(a.Value.id) - a.Min(a.Value.id) > 100)
                .ToListAsync(a => new
                {
                    a.Key.trade_no,
                    a.Key.logistics_no,
                    a.Key.spec_no,
                });


            // 找不到成本单价, (排除代发的)

            // 


            return noDatePrice.Select(a => new
                {
                    item = "没有日期的成本单价",
                    a.Stock, a.spec_no,
                    logistics_no = string.Empty,
                    trade_no = string.Empty,
                })
                .Concat(repeatPrice.Select(a => new {
                    item = "重复日期的成本单价",
                    a.Stock,
                    a.spec_no,
                    logistics_no = string.Empty,
                    trade_no = string.Empty,
                }))
                .Concat(repeatOut.Select(a => new
                {
                    item = "重复的出库明细",
                    Stock = string.Empty,
                    a.spec_no,
                    a.logistics_no,
                    a.trade_no,
                }))
                .Concat(repeatTrade.Select(a => new
                {
                    item = "重复的订单明细",
                    Stock = string.Empty,
                    a.spec_no,
                    a.logistics_no,
                    a.trade_no,
                }))
                .Select(a=> new {
                    项目 = a.item,
                    仓库 = a.Stock,
                    商家编码 = a.spec_no,
                    快递单号 = a.logistics_no,
                    订单编号 = a.trade_no,
                })
                .ToList();
 
        }


        private int GetTimesInSpecNo(string specno, int defaultQty, GoodsPrice g)
        {
            if(string.IsNullOrEmpty(specno) || specno.Contains("起拍") )
            {
                return defaultQty;
            }

            specno = specno.TrimEnd().TrimEnd('】');

            int qty = defaultQty;
            if(specno.Contains("10把") || specno.Contains("10个"))
            {
                qty = 10;
            }
            else if (specno.Contains("9把") || specno.Contains("9个"))
            {
                qty = 9;
            }
            else if (specno.Contains("8把") || specno.Contains("8个"))
            {
                qty = 8;
            }
            else if (specno.Contains("7把") || specno.Contains("7个"))
            {
                qty = 7;
            }
            else if (specno.Contains("6把") || specno.Contains("6个"))
            {
                qty = 6;
            }
            else if (specno.Contains("5把") || specno.Contains("5个"))
            {
                qty = 5;
            }
            else if (specno.Contains("4把") || specno.Contains("4个"))
            {
                qty = 4;
            }
            else if ((specno.Contains("3把") || specno.Contains("3个")) && specno.Contains("五梁椅-2-3") == false)
            {
                qty = 3;
            }
            else if ((specno.Contains("2把") || specno.Contains("2个") ) && specno.Contains("五梁椅-2-3") == false)
            {
                qty = 2;
            }

            return qty;

        }



    }


}
